import pygame
from datetime import datetime
import time
from DIDA_API import get_tasks
import myWeather
from zhdate import ZhDate
import json
import os
import random
import asyncio
import threading
import concurrent.futures

executor = concurrent.futures.ThreadPoolExecutor(max_workers=3)

# 字体文件
CN_FONT_PATH = "./fonts/cn.otf"
EN_FONT_PATH = "./fonts/en.ttf"

# 设置属性率
clock = pygame.time.Clock()
FPS = 5

# COLOR
THEME_COLOR_1 = (63, 186, 194)
THEME_COLOR_2 = (255, 189, 57)
THEME_COLOR_3 = (48, 56, 65)


BACKGROUND_COLOR = (24, 24, 24)
HOUR_COLOR = THEME_COLOR_1
MINUTE_COLOR = THEME_COLOR_2
APM_COLOR_1 = THEME_COLOR_1
APM_COLOR_2 = THEME_COLOR_3
SECOND_COLOR_1 = THEME_COLOR_1
SECOND_COLOR_2 = THEME_COLOR_3
DATE_COLOR = THEME_COLOR_2
WEEKDAY_COLOR = THEME_COLOR_2
ZHDATE_COLOR = THEME_COLOR_1
TEMP_COLOR = THEME_COLOR_2
WEATHER_COLOR = THEME_COLOR_1
TASK_COLOR = (180,180,180)
LINE_COLOR = THEME_COLOR_3
MARK_COLOR = THEME_COLOR_3
NIGHT_BACKGROUND_COLOR = (0, 0, 0)
NIGHT_TEXT_COLOR = (24, 24, 24)
# DYNAMIC_COLOR = ((23 + 38) / 2, (34 + 56) / 2, (59 + 89) / 2)

# 记录上次调用render_date的时间
last_dida_time = -1000
last_weather_time = -1000
last_forecast_time = -1000

tasks = []
weather_data = {}
forecast_data = {}

running = True

# 配置文件
with open("./ignore/config.json") as f:
    config = json.load(f)

# 初始化pygame
pygame.init()

# 获取当前屏幕分辨率
screen_info = pygame.display.Info()

if config["display"] == 0:
    screen_width, screen_height = screen_info.current_w, screen_info.current_h
    screen = pygame.display.set_mode((screen_width, screen_height), pygame.FULLSCREEN)
else:
    # 调试模式
    import ctypes

    ctypes.windll.shcore.SetProcessDpiAwareness(1)
    screen_width, screen_height = 1920, 1080
    screen = pygame.display.set_mode((screen_width, screen_height))


pygame.display.set_caption("RaspClock")

pygame.mouse.set_visible(False)

# 字体设置（根据屏幕大小动态调整字体大小）

# 时间字体
time_font_size = int(min(screen_width, screen_height) / 1.8)
time_font = pygame.font.Font(EN_FONT_PATH, time_font_size)

# 夜晚时间字体
night_time_font_size = int(min(screen_width, screen_height) / 1.5)
night_time_font = pygame.font.Font(EN_FONT_PATH, night_time_font_size)

#  上下午字体
apm_font_size = int(min(screen_width, screen_height) / 10)
apm_font = pygame.font.Font(EN_FONT_PATH, apm_font_size)

# 英文日期字体
en_date_font_size = int(min(screen_width, screen_height) / 6)
en_date_font = pygame.font.Font(EN_FONT_PATH, en_date_font_size)

# 星期字体
week_font_size = int(min(screen_width, screen_height) / 11)
week_font = pygame.font.Font(CN_FONT_PATH, week_font_size)

# 农历字体
zhdate_font_size = int(min(screen_width, screen_height) / 13)
zhdate_font = pygame.font.Font(CN_FONT_PATH, zhdate_font_size)

# 温度字体
temp_font_size = int(min(screen_width, screen_height) / 4)
temp_font = pygame.font.Font(EN_FONT_PATH, temp_font_size)

# 天气字体
weather_font_size = int(min(screen_width, screen_height) / 20)
weather_font = pygame.font.Font(CN_FONT_PATH, weather_font_size)

# 天气额外字体
# weather2_font_size = int(min(screen_width, screen_height) / 12)
# weather2_font = pygame.font.Font(CN_FONT_PATH, weather2_font_size)

# 任务字体
task_font_size = int(min(screen_width, screen_height) / 30)
task_font = pygame.font.Font(CN_FONT_PATH, task_font_size)

# 秒显示相关
left_list = [i for i in range(60)]
pick_list = []


def date_trans(indate):
    # 解析为 datetime 对象（注意时区处理）
    target_date = datetime.strptime(indate, "%Y-%m-%dT%H:%M:%S.%f%z")
    current_date = datetime.now(target_date.tzinfo)  # 保持相同时区
    # print(current_date)

    # 计算相差天数
    delta = target_date - current_date
    days_diff = delta.days + 1
    if days_diff == 0:
        return "今日"
    elif days_diff > 0:
        return str(days_diff) + "天后"
    else:
        return str(-days_diff) + "天前"


def move_random_to_pick():
    global pick_list, left_list
    if left_list:
        picked = random.choice(left_list)
        left_list.remove(picked)
        pick_list.append(picked)
        return picked
    return None  # 如果 left_list 为空，返回 None


def render_time():
    global screen, time_font
    ispm = False
    # 获取当前时间
    hour = datetime.now().strftime("%H")
    hour = int(hour)
    if hour > 12:
        ispm = True
        hour -= 12
    hour = str(hour)
    if len(hour) == 1:
        hour = "0" + hour

    minute = datetime.now().strftime("%M")
    second = int(datetime.now().strftime("%S"))
    # 渲染时间文本（居中显示）

    # 小时
    hour_text = time_font.render(hour, True, HOUR_COLOR)
    hour_center = (280, 280)
    hour_rect = hour_text.get_rect(center=hour_center)
    screen.blit(hour_text, hour_rect)

    # 分钟
    minute_text = time_font.render(minute, True, MINUTE_COLOR)  # 使用分钟变量
    minute_center = (hour_center[0] + 560, hour_center[1])  # Y轴下移50像素避免重叠
    minute_rect = minute_text.get_rect(center=minute_center)
    screen.blit(minute_text, minute_rect)  # 修正：应使用minute_text而非minute

    # 分隔符
    mark = time_font.render(":", True, MARK_COLOR)
    mark_center = ((minute_center[0] + hour_center[0]) / 2, hour_center[1] - 30)
    mark_rect = mark.get_rect(center=mark_center)

    if second % 2 == 1:
        screen.blit(mark, mark_rect)

    # 上下午
    am_color = APM_COLOR_1 if not ispm else APM_COLOR_2
    pm_color = APM_COLOR_1 if ispm else APM_COLOR_2

    am_text = apm_font.render("AM", True, am_color)
    pm_text = apm_font.render("PM", True, pm_color)

    am_center = (1170, 320)
    pm_center = (am_center[0], am_center[1] + 100)

    am_rect = am_text.get_rect(center=am_center)
    pm_rect = pm_text.get_rect(center=pm_center)

    screen.blit(am_text, am_rect)
    screen.blit(pm_text, pm_rect)

    # 显式释放Surface对象
    hour_text.unmap() if hasattr(hour_text, "unmap") else None
    minute_text.unmap() if hasattr(minute_text, "unmap") else None
    mark.unmap() if hasattr(mark, "unmap") else None
    am_text.unmap() if hasattr(am_text, "unmap") else None
    pm_text.unmap() if hasattr(pm_text, "unmap") else None

    # 秒显示
    start_pos = (70, 550)
    gap = 25
    square_width = 25
    bias_width = 10
    circle_radius = 5

    base_points = [
        [bias_width, 0],
        [square_width, 0],
        [square_width, square_width],
        [0, square_width],
        [0, bias_width],
    ]

    global pick_list, left_list
    if second == 0:
        second = 60
    if second < len(pick_list):
        pick_list = []
        left_list = [i for i in range(60)]

    while second > len(pick_list):
        move_random_to_pick()

    for i in range(60):
        if i in pick_list:
            pos = (
                start_pos[0] + (i % 20) * (square_width + gap),
                start_pos[1] + (i // 20) * (square_width + gap),
            )
            points = [[i[0] + pos[0], i[1] + pos[1]] for i in base_points]
            pygame.draw.polygon(screen, SECOND_COLOR_1, points)
        else:
            pos = (
                start_pos[0] + (i % 20) * (square_width + gap) + square_width / 2,
                start_pos[1] + (i // 20) * (square_width + gap) + square_width / 2,
            )
            pygame.draw.circle(screen, SECOND_COLOR_2, pos, circle_radius)


def render_date():
    global screen, date_font

    date_text = en_date_font.render(
        datetime.now().strftime("%Y/%m/%d"), True, DATE_COLOR
    )
    date_center = (420, 800)
    date_rect = date_text.get_rect(center=date_center)
    screen.blit(date_text, date_rect)

    weekdays = [
        "周一(月)",
        "周二(火)",
        "周三(水)",
        "周四(木)",
        "周五(金)",
        "周六(土)",
        "周日(日)",
    ]
    week_text = week_font.render(
        weekdays[datetime.now().weekday()], True, WEEKDAY_COLOR
    )
    week_center = (date_center[0] + 640, date_center[1] - 15)
    week_rect = week_text.get_rect(center=week_center)
    screen.blit(week_text, week_rect)

    # today = datetime.now()
    lunar_date = ZhDate.today()
    zh_date = " 农历" + lunar_date.chinese()[5:]

    zhdate_text = zhdate_font.render(zh_date, True, ZHDATE_COLOR)
    zhdate_rect = zhdate_text.get_rect(center=(620, 930))
    screen.blit(zhdate_text, zhdate_rect)


def render_tasks(tasks):
    global screen, task_font
    if len(tasks) > 0:
        gap = 100
        tasks = tasks[::-1]
        for i, task in enumerate(tasks):
            task_str = task[1]
            task_text = task_font.render(task_str, True, TASK_COLOR)
            task_rect = task_text.get_rect(
                left=1350,
                centery=920 - i * gap,
            )
            pygame.draw.rect(screen, LINE_COLOR, (1350, 970 - i * gap, 500, 2), 0)
            screen.blit(task_text, task_rect)

            if len(task) == 3:
                task_date_str = date_trans(task[2])
                task_date_text = task_font.render(task_date_str, True, TASK_COLOR)
                task_date_rect = task_date_text.get_rect(
                    right=1850,
                    centery=920 - i * gap,
                )
                screen.blit(task_date_text, task_date_rect)


def render_weather(weather_data):
    global screen, date_font

    temp = weather_data["now"]["temp"] + "°C"
    wtext = weather_data["now"]["text"]
    wind = weather_data["now"]["windDir"]
    humi = "湿度" + weather_data["now"]["humidity"] + "%"

    weather = wtext + " " + wind + " " + humi

    temp_center = (1600, 180)
    temp_text = temp_font.render(temp, True, TEMP_COLOR)
    temp_rect = temp_text.get_rect(center=temp_center)
    screen.blit(temp_text, temp_rect)

    wea_center = (1600, 350)
    wea_text = weather_font.render(weather, True, WEATHER_COLOR)
    wea_rect = wea_text.get_rect(center=wea_center)
    screen.blit(wea_text, wea_rect)



def render_forecast_weather(forecast_data):
    global screen
    weather = "明日 " + forecast_data["daily"][0]["textDay"]

    wea_center = (1600, 420)
    if "雨" in weather:
        wea_text = weather_font.render(weather, True, MINUTE_COLOR)
    else:
        wea_text = weather_font.render(weather, True, WEATHER_COLOR)
    wea_rect = wea_text.get_rect(center=wea_center)
    screen.blit(wea_text, wea_rect)



async def update_tasks_async(current_time):
    global last_dida_time, tasks
    if current_time - last_dida_time >= 300:
        last_dida_time = current_time
        loop = asyncio.get_event_loop()
        try:
            tmp = await loop.run_in_executor(executor, get_tasks)
            if tmp is not None and len(tmp) > 0:
                tasks = tmp
        except Exception as e:
            print(f"Error updating tasks: {e}")


async def update_weather_async(current_time):
    global last_weather_time, weather_data
    if current_time - last_weather_time >= 900:
        last_weather_time = current_time
        loop = asyncio.get_event_loop()
        try:
            tmp = await loop.run_in_executor(
                executor, lambda: myWeather.get_weather(config["locid"])
            )
            if tmp is not None and len(tmp) > 0:
                weather_data = tmp
        except Exception as e:
            print(f"Error updating weather: {e}")


async def update_forecast_async(current_time):
    global last_forecast_time, forecast_data
    if current_time - last_forecast_time >= 1800:
        last_forecast_time = current_time
        loop = asyncio.get_event_loop()
        try:
            tmp = await loop.run_in_executor(
                executor, lambda: myWeather.get_forecast_weather(config["locid"])
            )
            if tmp is not None and len(tmp) > 0:
                forecast_data = tmp
        except Exception as e:
            print(f"Error updating forecast: {e}")


async def update_all_data_async(current_time):
    """异步更新所有数据"""
    tasks = [
        update_tasks_async(current_time),
        update_weather_async(current_time),
        update_forecast_async(current_time),
    ]
    await asyncio.gather(*tasks, return_exceptions=True)


def render_day_mode(current_time):
    global last_dida_time, last_weather_time, tasks, weather_data, last_forecast_time, forecast_data
    screen.fill(BACKGROUND_COLOR)

    # render_dynamic_background()
    try:
        # 在当前线程的事件循环中运行异步任务
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        loop.run_until_complete(update_all_data_async(current_time))
        loop.close()
    except Exception as e:
        print(f"Error in async update: {e}")

    render_time()
    render_date()
    render_tasks(tasks)
    render_weather(weather_data)
    render_forecast_weather(forecast_data)

    pygame.draw.rect(screen, LINE_COLOR, (1290, 90, 2, 900), 0)


def render_night_mode():
    screen.fill(NIGHT_BACKGROUND_COLOR)
    time = datetime.now().strftime("%H:%M")
    time_text = night_time_font.render(time, True, NIGHT_TEXT_COLOR)
    time_center = (960, 540)
    time_rect = time_text.get_rect(center=time_center)
    screen.blit(time_text, time_rect)

    time_text.unmap() if hasattr(time_text, "unmap") else None


last_dynamic_background_color = 0


# def render_dynamic_background():
#     global screen
#     loop_length = 5000

#     time_mm = time.time() * 1000

#     pygame.draw.rect(
#         screen,
#         DYNAMIC_COLOR,
#         (int(1920 * ((time_mm % loop_length) / loop_length)), 540, 500, 20),
#         0,
#     )


while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:  # 按ESC退出全屏
                running = False

    current_time = time.time()  # 获取当前时间戳
    current_hour = datetime.fromtimestamp(current_time).hour

    # if True:
    if 0 <= current_hour < 7:
        render_night_mode()
    else:
        render_day_mode(current_time)

    clock.tick(FPS)  # 控制帧率
    pygame.display.flip()


pygame.quit()
